/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.query;

import edu.pdx.cs.guavadata.Channel;
import edu.pdx.cs.guavadata.Transform;
import edu.pdx.cs.guavadata.domain.Domain;
import edu.pdx.cs.guavadata.domain.Enumerated;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author VuTran
 */
public class UnpivotOp extends Operator {

    Operator child;
    String attCol;
    String valCol;
    String newAlias;
    List<String> foldColumns;

    public String getAttCol() {
        return attCol;
    }

    public void setAttCol(String attCol) {
        this.attCol = attCol;
    }

    public Operator getChild() {
        return child;
    }

    public void setChild(Operator child) {
        this.child = child;
    }

    public String getNewAlias() {
        return newAlias;
    }

    public void setNewAlias(String newAlias) {
        this.newAlias = newAlias;
    }

    public String getValCol() {
        return valCol;
    }

    public void setValCol(String valCol) {
        this.valCol = valCol;
    }

    public List<String> getFoldColumns() {
        return foldColumns;
    }

    public void setFoldColumns(List<String> foldColumns) {
        this.foldColumns = foldColumns;
    }

    public UnpivotOp(Operator child, List<String> foldColumns, String attCol, String valCol, String newAlias) {
        this.child = child;
        child.parent = this;
        this.attCol = attCol;
        this.valCol = valCol;
        this.newAlias = newAlias;
        this.foldColumns = new ArrayList<String>(foldColumns);

        try {
            // Create output schema - make sure that the domains of the various fold columns are equal
            Domain dWorking = null;
            exposedColumns = new ArrayList<String>();
            exposedDomains = new ArrayList<Domain>();
            for (int i = 0; i < child.exposedColumns.size(); i++) {
                if (this.foldColumns.contains(child.exposedColumns.get(i))) {
                    if (dWorking == null) {
                        dWorking = child.exposedDomains.get(i);
                    } else if (dWorking != child.exposedDomains.get(i)) {
                        throw new Exception("Columns in the fold list of the unpivot operator do not have like domains.");
                    }
                } else {
                    exposedColumns.add(child.exposedColumns.get(i));
                    exposedDomains.add(child.exposedDomains.get(i));
                }
            }

            // If dWorking is still null, then we didn't find any pivot columns, and there is an error
            if (dWorking == null)
                throw new Exception("Did not find any pivot columns.");

            Enumerated e = new Enumerated(foldColumns);
            this.exposedColumns.add(attCol);
            this.exposedColumns.add(valCol);
            this.exposedDomains.add(e);
            this.exposedDomains.add(dWorking);
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }
    }

    @Override
    public SqlText visit(Provider qv) {
        return qv.transform(this);
    }

    @Override
    public void visit(Channel c, String table) {
        c.mapAliases(this, table);
    }

    @Override
    public void visit(Transform t, Command c) {
        t.expand(this, c);
    }

    @Override
    public void notifyChange(Operator old, Operator newOp) {
        if (child == old) {
            this.child = newOp;
            newOp.parent = this;
        }
    }

    @Override
    public Operator clone() {
        return new UnpivotOp(child.clone(), foldColumns, attCol, valCol, newAlias);
    }
}
